<?php
use Firebase\JWT\JWT;
use Endroid\QrCode\QrCode;
use PHPMailer\PHPMailer\PHPMailer;

class Tools
{

    private static $key = 'e10adc3949ba59abbe56e057f20f883e';
    public static $redis_z = '';
    /**
     * 跳转
     *
     * @param      $url
     * @param null $headers     */
    public static function redirect($url, $headers = null)
    {
        if (!empty($url)) {
            if ($headers) {
                if (!is_array($headers))
                    $headers = array($headers);

                foreach ($headers as $header)
                    header($header);
            }

            header('Location: ' . $url);
            exit;
        }
    }

    /**
     * 获取用户IP地址
     *
     * @return mixed
     */
    public static function getRemoteAddr()
    {
        if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && $_SERVER['HTTP_X_FORWARDED_FOR'] && (!isset($_SERVER['REMOTE_ADDR']) || preg_match('/^127\..*/i', trim($_SERVER['REMOTE_ADDR'])) || preg_match('/^172\.16.*/i', trim($_SERVER['REMOTE_ADDR'])) || preg_match('/^192\.168\.*/i', trim($_SERVER['REMOTE_ADDR'])) || preg_match('/^10\..*/i', trim($_SERVER['REMOTE_ADDR'])))) {
            if (strpos($_SERVER['HTTP_X_FORWARDED_FOR'], ',')) {
                $ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);

                return $ips[0];
            } else
                return $_SERVER['HTTP_X_FORWARDED_FOR'];
        }

        return $_SERVER['REMOTE_ADDR'];
    }

    /**
     * 获取公网ip
     */
    public static function getoutip(){
        $ch = curl_init('http://tool.huixiang360.com/zhanzhang/ipaddress.php');
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $a  = curl_exec($ch);
        preg_match('/\[(.*)\]/', $a, $ip);
        return $ip[1];
    }
    /**
     * 获取用户来源地址
     *
     * @return null
     */
    public static function getReferer()
    {
        if (isset($_SERVER['HTTP_REFERER'])) {
            return $_SERVER['HTTP_REFERER'];
        } else {
            return null;
        }
    }

    /**
     * 显示错误信息
     *
     * @param string $string
     * @param array  $error
     * @param bool   $htmlentities
     *
     * @return mixed|string
     */
    public static function displayError($string = 'Fatal error', $error = array(), $htmlentities = true) {
        if (DEBUG_MODE)
        {
            if (!is_array($error) || empty($error))
                return str_replace('"', '&quot;', $string) . ('<pre>' . print_r(debug_backtrace(), true) . '</pre>');
            $key = md5(str_replace('\'', '\\\'', $string));
            $str = (isset($error) AND is_array($error) AND key_exists($key, $error)) ? ($htmlentities ? htmlentities($error[$key], ENT_COMPAT, 'UTF-8') : $error[$key]) : $string;

            return str_replace('"', '&quot;', stripslashes($str));
        }
        else
        {
            return str_replace('"', '&quot;', $string);
        }
    }
    public static function nl2br($str){
        return preg_replace("/((<br ?\/?>)+)/i", "<br />", str_replace(array("\r\n", "\r", "\n"), "<br />", $str));
    }

    public static function setCookie($name, $content, $time = null, $path = '/', $domain = '.sse100.com')
    {
        if(empty($time))$time = time()+7200;
//        echo USER_COOKIE_SHARED;
        ob_clean();
        if (PHP_VERSION_ID <= 50200) /* PHP version > 5.2.0 */
            return setcookie($name, $content, $time, $path, $domain, 0);
        else {
            return setcookie($name, $content, $time, $path, $domain, 0, false);
        }
    }
    /**
     * 截取字符串，支持中文
     *
     * @param        $str
     * @param        $max_length
     * @param string $suffix
     *
     * @return string
     */
    public static function truncate($str, $max_length, $suffix = '...')
    {
        if (Tools::strlen($str) <= $max_length)
            return $str;
        $str = utf8_decode($str);

        return (utf8_encode(substr($str, 0, $max_length - Tools::strlen($suffix)) . $suffix));
    }
    /**
     * 判断是否真为空
     *
     * @param $field
     *
     * @return bool
     */
    public static function isEmpty($field)
    {
        return ($field === '' || $field === null);
    }

    /**
     * @param        $url
     * @param string $method
     * @param null $postFields
     * @param null $header
     *
     * @return mixed
     * @throws Exception
     */
    public static function curl($url, $method = 'GET', $postFields = null, $header = null, $cookie = null, $savecookie = null)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
        curl_setopt($ch, CURLOPT_FAILONERROR, false);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
//        curl_setopt($ch, CURLOPT_NOSIGNAL, 1);

        if (strlen($url) > 5 && strtolower(substr($url, 0, 5)) == "https") {
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        }
        switch ($method) {
            case 'POST':
                if (!empty($postFields)) {
                    if (is_array($postFields) || is_object($postFields)) {
                        if (is_object($postFields))
                            $postFields = Tools::object2array($postFields);
                        $postBodyString = "";
                        $postMultipart = false;
                        foreach ($postFields as $k => $v) {
                            if ("@" != substr($v, 0, 1) || in_array($k, array("name", "nick"))) { //判断是不是文件上传
                                $postBodyString .= "$k=" . urlencode($v) . "&";
                            } else { //文件上传用multipart/form-data，否则用www-form-urlencoded
                                $postMultipart = true;
                                if(class_exists("CURLFile")){
                                    $postFields[$k] = new CURLFile(realpath(str_replace("@", "", $v)));
                                }
                            }
                        }
                        unset($k, $v);
                        if ($postMultipart) {
                            if (class_exists("CURLFile")) {
                                curl_setopt($ch, CURLOPT_SAFE_UPLOAD, true);
                            } else {
                                if (defined('CURLOPT_SAFE_UPLOAD')) {
                                    curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);
                                }
                            }
                            curl_setopt($ch, CURLOPT_POST, true);
                            curl_setopt($ch, CURLOPT_NOSIGNAL, 1);
                            curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
                        } else {
                            curl_setopt($ch, CURLOPT_POST, true);
                            curl_setopt($ch, CURLOPT_POSTFIELDS, substr($postBodyString, 0, -1));
                        }
                    } else {
                        curl_setopt($ch, CURLOPT_POST, true);
                        curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
                    }
                }
                break;
            case 'PUT':
                if (!empty($postFields)) {
                    if (is_array($postFields) || is_object($postFields)) {
                        if (is_object($postFields))
                            $postFields = Tools::object2array($postFields);
                        $postBodyString = "";
                        $postMultipart = false;
                        foreach ($postFields as $k => $v) {
                            if ("@" != substr($v, 0, 1)) { //判断是不是文件上传
                                $postBodyString .= "$k=" . urlencode($v) . "&";
                            } else { //文件上传用multipart/form-data，否则用www-form-urlencoded
                                $postMultipart = true;
                                if(class_exists("CURLFile")){
                                    $postFields[$k] = new CURLFile(realpath(str_replace("@", "", $v)));
                                }
                            }
                        }
                        unset($k, $v);
                        if ($postMultipart) {
                            if (class_exists("CURLFile")) {
                                curl_setopt($ch, CURLOPT_SAFE_UPLOAD, true);
                            } else {
                                if (defined('CURLOPT_SAFE_UPLOAD')) {
                                    curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);
                                }
                            }
                            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
                            curl_setopt($ch, CURLOPT_NOSIGNAL, 1);
                            curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
                        } else {
                            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
                            curl_setopt($ch, CURLOPT_POSTFIELDS, substr($postBodyString, 0, -1));
                        }
                    } else {
                        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
                        curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
                    }

                }
                break;
            case 'DELETE':
                curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
                break;
            case 'GET':
                if (!empty($postFields) && is_array($postFields))
                    $url .= (strpos($url, '?') === false ? '?' : '&') . http_build_query($postFields);
                break;
            default:
                if (!empty($postFields) && is_array($postFields))
                    $url .= (strpos($url, '?') === false ? '?' : '&') . http_build_query($postFields);
                break;
        }
        curl_setopt($ch, CURLOPT_URL, $url);

        if (!empty($header) && is_array($header)) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        }
        if(!empty($savecookie)){
            curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie);
        } else {
            if (!empty($cookie)) {
                curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie); //读取cookie
            }
        }
        $response = curl_exec($ch);


        if(isset($_GET['debug']) && $_GET['debug'] == 1){
            var_dump(curl_error($ch));
            $aStatus = curl_getinfo($ch);
            var_dump($aStatus);
        }
//        var_dump(curl_errno($ch));
        if (curl_errno($ch)) {
            //throw new Exception(curl_error($ch), 0);
        }
        curl_close($ch);

        return $response;
    }
    public static function object2array(&$object) {
        return json_decode(json_encode($object), true);
    }

    /**
     * 获取扩展名
     * @param $file
     * @return mixed
     */
    public static function getExt($file)
    {
        $fileArr = explode('.', $file);
        return $fileArr[count($fileArr) - 1];
    }

    public static function getFilePath($file_path, $type = 'image')
    {
        if ($type == 'image') {
            if (substr($file_path, 0, 4) == 'http') {
                return $file_path;
            } else {
                return IMAGE_SERVER . (substr($file_path, 0, 1) == '/' ? $file_path : '/'.$file_path);
            }
        } else if ($type == 'video' || $type == 'voice') {
            if (substr($file_path, 0, 4) == 'http') {
                return $file_path;
            } else {
                return VIDEO_SERVER . (substr($file_path, 0, 1) == '/' ? $file_path : '/'.$file_path);
            }
        }
    }

    public static function checkArrayResult($arr) {
        if (! is_array($arr)) return false;
        foreach($arr as $a) {
            if (! $a) return false;
        }
        return true;
    }
    /**
     * XML文档转为数组
     * @param string $xml XML文档字符串
     * @return array
     */
    public static function xmlToArray($xml) {
        return $xml ? self::xmlToArrayElement(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)) : array();
    }

    /**
     * 数组转为XML
     * @param $arr
     * @param int $dom
     * @param int $item
     * @return string
     */
    public static function arrayToXml($arr,$dom=0,$item=0){
        if (!$dom){
            $dom = new DOMDocument("1.0");
        }
        if(!$item){
            $item = $dom->createElement("response");
            $dom->appendChild($item);
        }
        foreach ($arr as $key=>$val){
            $itemx = $dom->createElement(is_string($key)?$key:"item");
            $item->appendChild($itemx);
            if (!is_array($val)){
                $text = $dom->createTextNode($val);
                $itemx->appendChild($text);

            }else {
                self::arrayToXml($val,$dom,$itemx);
            }
        }
        return $dom->saveXML();
    }
    /**
     * xml文档转为数组元素
     * @param obj $xmlobject XML文档对象
     * @return array
     */
    public static function xmlToArrayElement($xmlobject) {
        $data = array();
        foreach ((array) $xmlobject as $key => $value) {
            $data[$key] = !is_string($value) ? self::xmlToArrayElement($value) : $value;
        }
        return $data;
    }

    public static function cutStr($sourcestr,$cutlength, $cuttype = false) {
        $returnstr = '';
        $i = 0;
        $n = 0;
        if($cuttype) {
            $cutlength = 9999999999999;
        }
        //字符串的字节数
        $str_length = strlen($sourcestr);
        while (($n < $cutlength) and ($i <= $str_length)) {
            $temp_str = substr($sourcestr, $i, 1);
            //得到字符串中第$i位字符的ascii码
            $ascnum = Ord($temp_str);
            //如果ASCII位高与224
            if ($ascnum >= 224) {
                //根据UTF-8编码规范，将3个连续的字符计为单个字符
                $returnstr = $returnstr.substr($sourcestr, $i, 3);
                //实际Byte计为3
                $i = $i + 3;
                //字串长度计1
                $n++;
                //如果ASCII位高与192，
            } elseif ($ascnum >= 192) {
                //根据UTF-8编码规范，将2个连续的字符计为单个字符
                $returnstr = $returnstr.substr($sourcestr, $i, 2);
                $i = $i + 2; //实际Byte计为2
                $n++; //字串长度计1
                //如果是大写字母，
            } elseif ($ascnum >= 65 && $ascnum <= 90) {
                $returnstr = $returnstr.substr($sourcestr, $i, 1);
                //实际的Byte数仍计1个
                $i = $i + 1;
                //但考虑整体美观，大写字母计成一个高位字符
                $n++;
                //其他情况下，包括小写字母和半角标点符号，
            } else {
                $returnstr = $returnstr.substr($sourcestr, $i, 1);
                //实际的Byte数计1个
                $i = $i + 1;
                //小写字母和半角标点等与半个高位字符宽…
                $n = $n + 0.5;
                //$n++;
            }
        }
        if ($str_length > $cutlength) {
            //超过长度时在尾处加上省略号
            //$returnstr = $returnstr . “…”;
        }
        if($cuttype){
            return $n-0.5;
        } else {
            return $returnstr;
        }
    }


    /**
     * 获取签名
     * @param $appid
     * @param $appserect
     * @param $noncestr
     * @param $timestamp
     * @param $key
     * @return string
     */
    public static function getSign($appid, $appserect, $noncestr ,$timestamp, $key){
        $arr = array(
            "appid" => $appid,
            "appserect" => $appserect,
            "noncestr" => $noncestr,
            "timestamp" => $timestamp
        );
        //签名步骤一：按字典序排序参数
        ksort($arr);
        $string = self::ToUrlParams($arr);
        //签名步骤二：在string后加入KEY
        $string = $string . "&key=".$key;
        //签名步骤三：MD5加密
        $string = md5($string);
        //签名步骤四：所有字符转为大写
        $result = strtoupper($string);
        return $result;
    }
    /**
     * 格式化参数格式化成url参数
     */
    public static function ToUrlParams($arr) {
        $buff = "";
        foreach ($arr as $k => $v)
        {
            if($k != "sign" && $v != "" && !is_array($v)){
                $buff .= $k . "=" . $v . "&";
            }
        }
        $buff = trim($buff, "&");
        return $buff;
    }
    /**
     * 生成签名
     * @return 签名，本函数不覆盖sign成员变量，如要设置签名需要调用SetSign方法赋值
     */
    public static function MakeSign($values,$key)
    {
        //签名步骤一：按字典序排序参数
        ksort($values);
        $string = self::ToUrlParams($values);
        //签名步骤二：在string后加入KEY
        $string = $string.$key;
        //签名步骤三：MD5加密
        $string = md5($string);
        //签名步骤四：所有字符转为大写
        $result = strtoupper($string);
        return $result;
    }
    public static function MakeYBSign($values,$key)
    {
        //签名步骤一：按字典序排序参数
        ksort($values);
        $string = self::ToUrlParams($values);
        //签名步骤二：在string后加入KEY
        $string = $string.'&access_token='.$key;
        //签名步骤三：MD5加密
        $string = md5($string);
        return $string;
    }
    /**
     * 生成签名
     * @return 签名，本函数不覆盖sign成员变量，如要设置签名需要调用SetSign方法赋值
     */
    public static function MakeAliSign($values,$key)
    {
        //签名步骤一：按字典序排序参数
        ksort($values);
        $string = self::ToUrlParams($values);
        //签名步骤二：在string后加入KEY
        $string = $string.$key;
        //签名步骤三：MD5加密
//        var_dump($string);
        $string = md5($string);
        //签名步骤四：所有字符转为大写
//        $result = strtoupper($string);
        return $string;
    }


    public static function getMenuArr($type='admin'){
        $arr = self::foreachDir(APPLICATION_PATH.DIRECTORY_SEPARATOR.'plugins'.DIRECTORY_SEPARATOR, $type);
        return $arr;
    }

    public static function foreachDir($directory,$type){
        $filearr = array();
        $mydir = dir($directory);
        while($file = $mydir->read())
        {
            if((is_dir("$directory/$file")) AND ($file!=".") AND ($file!=".."))
            {
                if(($file!=".") AND ($file!="..")){
                    $arr = self::loadIniConf($directory.$file.DIRECTORY_SEPARATOR."conf".DIRECTORY_SEPARATOR."conf.ini");
                    if($arr['plugins'][$type]){
                        if(is_array($arr['plugins'][$type.'menu'])){
                            foreach($arr['plugins'][$type.'menu'] as &$v){
                                $v['path'] = WEB_SERVER."/plugins/".$type."/".$arr['plugins']['key']."/".$v['key'];
                            }
                        }
                        $filearr[] = array(
                            "name" => $arr['plugins']['name'],
                            "key" => $arr['plugins']['key'],
                            "path" => WEB_SERVER."/plugins/".$type."/".$arr['plugins']['key']."/".$arr['plugins'][$type.'default'],
                            'menu' => $arr['plugins'][$type.'menu']
                        );
                    }
                }
//                tree("$directory/$file");
            } else {
//                if(($file!=".") AND ($file!="..")){
//                    $filearr[] = $file;
//                }
            }
        }
        $mydir->close();
        return $filearr;
    }

    public static function loadIniConf($file){
        $iniArray = array();
        if(file_exists($file)) {
            $loaded = parse_ini_file($file, true);
            foreach ($loaded as $key => $data) {
                $pieces = explode('.', $key);
                switch (count($pieces)) {
                    case '1':
                        $iniArray[trim($pieces[0])] = $data;
                        break;
                    case '2':
                        $iniArray[trim($pieces[0])][trim($pieces[1])] = $data;
                        break;
                    case '3':
                        $iniArray[trim($pieces[0])][trim($pieces[1])][trim($pieces[2])] = $data;
                        break;
                    case '4':
                        $iniArray[trim($pieces[0])][trim($pieces[1])][trim($pieces[2])][trim($pieces[3])] = $data;
                        break;
                    case '5':
                        $iniArray[trim($pieces[0])][trim($pieces[1])][trim($pieces[2])][trim($pieces[3])][trim($pieces[4])] = $data;
                        break;
                }
            }
        }
        return $iniArray;
    }

    public static function createNonceStr($length = 16,$type='0') {
        if($type == 0){
            $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
            $str = "";
            for ($i = 0; $i < $length; $i++) {
                $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
            }
        }else{
            $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*";
            $str = "";
            for ($i = 0; $i < $length; $i++) {
                $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
            }
        }
        return $str;
    }
    public static function download_file($file,$name){
        $file_size = filesize($file);
        header("Content-type: application/octet-stream;charset=utf8");
        header("Accept-Ranges: bytes");
        header("Accept-Length: $file_size");
        header("Content-Disposition: attachment; filename=\"$name\"");

        $fp = fopen($file,"r");
        $buffer_size = 1024;
        $cur_pos = 0;
        while(!feof($fp)&&$file_size-$cur_pos>$buffer_size){
            $buffer = fread($fp,$buffer_size);
            echo $buffer;
            $cur_pos+=$buffer_size;
        }
        $buffer = fread($fp,$file_size-$cur_pos);
        echo $buffer;
        fclose($fp);
        unlink($file);
        return true;
    }


    /**
     * 以post方式提交xml到对应的接口url
     *
     * @param string $xml  需要post的xml数据
     * @param string $url  url
     * @param bool $useCert 是否需要证书，默认不需要
     * @param int $second   url执行超时时间，默认30s
     * @return mixed
     * @throws WxPayException
     */
    public static function postXmlCurl($xml, $url, $useCert = false, $second = 30)
    {
        $ch = curl_init();
        //设置超时
        curl_setopt($ch, CURLOPT_TIMEOUT, $second);

        //如果有配置代理这里就设置代理
        if(Config::CURL_PROXY_HOST != "0.0.0.0"
            && Config::CURL_PROXY_PORT != 0){
            curl_setopt($ch,CURLOPT_PROXY, Config::CURL_PROXY_HOST);
            curl_setopt($ch,CURLOPT_PROXYPORT, Config::CURL_PROXY_PORT);
        }
        curl_setopt($ch,CURLOPT_URL, $url);
        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TRUE);
        curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//严格校验
        //设置header
        curl_setopt($ch, CURLOPT_HEADER, FALSE);
        //要求结果为字符串且输出到屏幕上
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);

        if($useCert == true){
            //设置证书
            //使用证书：cert 与 key 分别属于两个.pem文件
            curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
            curl_setopt($ch,CURLOPT_SSLCERT, Config::getSSLCERT_PATH());
            curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
            curl_setopt($ch,CURLOPT_SSLKEY, Config::getSSLKEY_PATH());
        }
        //post提交方式
        curl_setopt($ch, CURLOPT_POST, TRUE);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
        //运行curl
        $data = curl_exec($ch);
        //返回结果
        if($data){
            curl_close($ch);
            return $data;
        } else {
            $error = curl_errno($ch);
            curl_close($ch);
            throw new WxPayException("curl出错，错误码:$error");
        }
    }

    /**
     * 设置缓存，按需重载
     * @param string $cachename
     * @param mixed $value
     * @param int $expired
     * @return boolean
     */
    public static function setCache($cachename,$value,$expired = 0){
        //TODO: set cache implementation
        if(! self::$redis)self::$redis = self::getRedis();
        $value = serialize($value);
        $a = self::$redis->write($cachename, $value,$expired);
        return $a;
    }
    /**
     * 设置缓存，按需重载
     * @param string $cachename
     * @param mixed $value
     * @param int $expired
     * @return boolean
     */
    public static function R_set($cachename,$value,$expired = 0){
        //TODO: set cache implementation
        if(! self::$redis)self::$redis = self::getRedis();
        $a = self::$redis->write($cachename, $value,$expired);
        return $a;
    }
    public static function R_get($cachename){
        //TODO: set cache implementation
        if(! self::$redis)self::$redis = self::getRedis();
        $a = self::$redis->read($cachename);
        return $a;
    }
    /**
     * 获取缓存，按需重载
     * @param string $cachename
     * @return mixed
     */
    public static function getCache($cachename){
        //TODO: get cache implementation
        if(! self::$redis)self::$redis = self::getRedis();
        $value = self::$redis->read($cachename);
        if(empty($value) === FALSE && $value != 'i:0;' && !is_numeric($value)){
            return unserialize($value);
        }
        return null;
    }
    public static function getkeys($cachename){
        //TODO: get cache implementation
        if(! self::$redis)self::$redis = self::getRedis();
        $value = self::$redis->keys($cachename);
        if(empty($value) === FALSE){
            return $value;
        }
        return null;
    }

    public static function get($cachename){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->get($cachename);
    }
    public static function set($cachename,$value=0,$time=7200){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->set($cachename,$value,$time);
    }
    /**
     * 清除缓存，按需重载
     * @param string $cachename
     * @return boolean
     */
    public static function removeCache($cachename){
        //TODO: remove cache implementation
        if(! self::$redis)self::$redis = self::getRedis();
        return self::$redis->destroy($cachename);
    }
    /**
     * redis集合存储
     */
    public static function zadd($cachename,$score,$data){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->zAdd($cachename,$score,$data);
    }
    public static function zcard($cachename){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->zCard($cachename);
    }
    /**
     * 根据分值倒序获取元素
     * @param $cachename
     * @param $num
     * @return array
     */
    public static function zrevrange($cachename,$s_num=0,$e_num){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->zRevRange($cachename,$s_num,$e_num);
    }
    /**
     * 根据分值倒序获取元素
     * @param $cachename
     * @param $num
     * @return array
     */
    public static function zrevrangebyscore($cachename,$s_num=0,$e_num){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->zRemRangeByScore($cachename,$s_num,$e_num);
    }
    /**
     * 根据分值顺序获取元素
     * @param $cachename
     * @param $num
     * @return array
     */
    public static function zrange($cachename,$num,$start = 0,$withscores=null){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->zRange($cachename,$start,$num,$withscores);
    }

    /**
     * 根据分数获取区间值  如果两个值相同则获取该分数对应的集合值
     * @param $cachename
     * @param $score1
     * @param $score2
     * @return array
     */
    public static function zrangebyscore($cachename,$score1,$score2){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->zRangeByScore($cachename,$score1,$score2);
    }

    /**
     * 计算有序集合中指定分数区间的成员数量
     * @param $cachename
     * @param $score1
     * @param $score2
     * @return int
     */
    public static function zcount($cachename,$score1,$score2){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->zCount($cachename,$score1,$score2);
    }
    public static function zscore($cachename,$member){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->zScore($cachename,$member);
    }
    /**
     * 删除指定集合中元素
     * @param $cachename
     * @param $arr_title
     * @return bool
     */
    public static function zrem($cachename,$arr_title){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        if(empty($arr_title) === FALSE){
            foreach ($arr_title as &$v){
                self::$redis_z->zRem($cachename,$v);
            }
        }
        return true;
    }
    /**
     * 设置缓存过期
     * @param $cachename
     * @return bool
     */
    public static function expireCache($cachename){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->expire($cachename,-1);
    }
    public static function rpush($cachename,$value){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->rPush($cachename,$value);
    }
    //------------------------------------------无序集合

    /**向集合添加一个或多个成员
     * @param $cachename
     * @param $value
     * @return bool|int
     */
    public static function sadd($cachename,$value){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->sAdd($cachename,$value);
    }
    /**获取集合的成员数
     * @param $cachename
     * @param $value
     * @return bool|int
     */
    public static function scard($cachename){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->sCard($cachename);
    }
    /**返回第一个集合与其他集合之间的差异。
     * @param $cachename
     * @param $value
     * @return bool|int
     */
    public static function sdiff($cachename1,$cachename2){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->sDiff($cachename1,$cachename1);
    }
    /**返回给定所有集合的交集。
     * @param $cachename
     * @param $value
     * @return bool|int
     */
    public static function sinter($cachename1,$cachename2){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->sInter($cachename1,$cachename1);
    }
    /**判断 member 元素是否是集合 key 的成员。
     * @param $cachename
     * @param $value
     * @return bool|int
     */
    public static function sismember($cachename1,$value){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->sIsMember($cachename1,$value);
    }
    /**返回集合中的所有成员。
     * @param $cachename
     * @param $value
     * @return bool|int
     */
    public static function smember($cachename1){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->sMembers($cachename1);
    }
    /**返回集合中的所有成员。
     * @param $cachename
     * @param $value
     * @return bool|int
     */
    public static function sunion($cachename1,$cachename2){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->sUnion($cachename1,$cachename2);
    }
    /**移除并返回集合中的一个随机元素。
     * @param $cachename
     * @param $value
     * @return bool|int
     */
    public static function spop($cachename1){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->sPop($cachename1);
    }
    /**
     * 设置缓存过期
     * @param $cachename
     * @return bool
     */
    public static function setexpireCache($cachename,$ttl){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();
            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->expire($cachename,$ttl);
    }
    /**
     * 获取缓存时间
     * @param $cachename
     * @return bool
     */
    public static function getttl($cachename){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->ttl($cachename);
    }
    /**
     * 获取redis对象
     */
    public static function getRedis(){
        if(!self::$redis){
            self::$redis = new \think\session\driver\Redis();
        }
        return self::$redis;
    }
    //队列
    public static function l_pop($cache_name){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->lPop($cache_name);
    }
    public static function r_pop($cache_name){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->rPop($cache_name);
    }
    public static function l_push($cache_name,$value){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->lPush($cache_name,$value);
    }
    public static function l_trim($cache_name,$start = 0,$end = 0){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->lTrim($cache_name,$start,$end);
    }
    public static function r_push($cache_name,$value){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->rPush($cache_name,$value);
    }
    public static function l_range($cache_name,$start,$end){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->lRange($cache_name,$start,$end);
    }
    public static function l_len($cache_name){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->lLen($cache_name);
    }

    /**
     * 递增因子
     * @param $cache_name
     * @return bool|int
     */
    public static function incr($cache_name){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->incr($cache_name);
    }
    public static function incrBy($cache_name,$num=1){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->incrBy($cache_name,$num);
    }
    /**
     * redis hash  删除一个或多个哈希表字段
     */
    public static function hdel($cache_name,$field){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->hDel($cache_name,$field);
    }

    /**
     * 查看哈希表 key 中，指定的字段是否存在
     * @param $cache_name
     * @return bool
     */
    public static function hexists($cache_name,$field){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->hExists($cache_name,$field);
    }
    /**
     * 获取存储在哈希表中指定字段的值
     * @param $cache_name
     * @return bool
     */
    public static function hget($cache_name,$field){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->hGet($cache_name,$field);
    }
    /**
     * 获取在哈希表中指定 key 的所有字段和值
     * @param $cache_name
     * @return bool
     */
    public static function hgetall($cache_name){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->hGetAll($cache_name);
    }
    /**
     * 为哈希表 key 中的指定字段的整数值加上增量 increment
     * @param $cache_name
     * @return bool
     */
    public static function hincrby($cache_name,$field,$increment=1){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->hIncrBy($cache_name,$field,$increment);
    }
    /**
     * 获取所有哈希表中的字段
     * @param $cache_name
     * @return bool
     */
    public static function hkeys($cache_name){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->hKeys($cache_name);
    }
    /**
     * 获取哈希表中字段的数量
     * @param $cache_name
     * @return bool
     */
    public static function hlen($cache_name){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->hLen($cache_name);
    }
    /**
     * 获取所有给定字段的值
     * @param $cache_name
     * @return bool
     */
    public static function hmget($cache_name,$field){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->hMGet($cache_name,$field);
    }
    /**
     * 同时将多个 field-value (域-值)对设置到哈希表 key 中
     * @param $cache_name
     * @return bool
     */
    public static function hmset($cache_name,$field){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->hMSet($cache_name,$field);
    }
    /**
     * 将哈希表 key 中的字段 field 的值设为 value 。
     * @param $cache_name
     * @return bool
     */
    public static function hset($cache_name,$field,$value=1){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->hSet($cache_name,$field,$value);
    }
    /**
     * 只有在字段 field 不存在时，设置哈希表字段的值。
     * @param $cache_name
     * @return bool
     */
    public static function hsetnx($cache_name,$field,$value){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->hSetNx($cache_name,$field,$value);
    }
    /**
     * 获取哈希表中所有值。
     * @param $cache_name
     * @return bool
     */
    public static function hvals($cache_name){
        if(!self::$redis_z) {
            self::$redis_z = new \Redis();

            self::$redis_z->pconnect('127.0.0.1', '6379', 7200);
        }
        return self::$redis_z->hVals($cache_name);
    }
    /**
     * @param $start_date
     * @param string $type
     * @param $end_date
     * @return false|int|string|null
     */
    public static function getNextDay($start_date, $type = 'none', $end_date) {
        if($type == 'none'){
            $date = 0;
        } else if($type == 'month') {
            $date = strtotime($start_date." +1month");
        } else if($type == 'quarter') {
            $date = strtotime($start_date." +3month");
        } else if($type == 'halfyear') {
            $date = strtotime($start_date." +6month");
        } else if($type == 'year') {
            $date = strtotime($start_date." +12month");
        }
        if($date > strtotime($end_date)) $date = 0;

        if($date < 1) return null;

        $date = date("Y-m-d", $date);
        if(time() > strtotime($date)){
            $date = self::getNextDay($date, $type, $end_date);
        }

        return $date;
    }

    public static function encrypt($code){
        return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5(Yaf_Registry::get('config')->common->TOKEN_KEY), $code, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND)));
    }
    public static function decrypt($code){
        return mcrypt_decrypt(MCRYPT_RIJNDAEL_256, md5(Yaf_Registry::get('config')->common->TOKEN_KEY), base64_decode($code), MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND));
    }

    /**
     * 生成登录token
     * @return array
     */
    public static function getToken($unionid, $userId, $token=''){
        if(!$token){
            $token = md5($unionid . rand(1000,9999) . $userId);
        }
        $timestamp = time();
        $a1 = self::encrypt($timestamp.';'.$token.';'.$userId);
        return $a1;
    }
    /**
     * 解码TOKEN
     **/
    public static function decryptToken($token){
        $userToken = self::decrypt($token);
        $userid_arr = explode(";", $userToken);
        $user_id    = isset($userid_arr[2]) ? (int)$userid_arr[2] : 0;
        return $user_id;
    }



    public static function setLog($data = array()){
        $log = new AdminLogService();
        return $log->setLog($data);
    }
    //签发token
    public static function signJWTToken($data){
        $token = array(
            "iss"   => "newAction", //签发者
            "time"  => self::getDateTimeByTime(), //签发时间
            'data'  => $data //可以用户ID，可以自定义
        );
        $jwt = new JWT();
        $jwt = $jwt::encode($token, self::$key,'HS256');
        return $jwt;
    }
    //验证token
    public static function checkJWTToken($token){
        try {
//            JWT::$leeway = 60;//当前时间减去60，把时间留点余地
            $decoded = JWT::decode($token, self::$key, array('HS256')); //HS256方式，这里要和签发的时候对应
            $arr = (array)$decoded;
            $arr = (array)$arr['data'];
            return $arr;

        } catch(\Firebase\JWT\SignatureInvalidException $e) { //签名不正确
            return self::returnMsg(false,array('code'=>'10001','message'=>'签名不正确'));
        }catch(\Firebase\JWT\BeforeValidException $e) { // 签名在某个时间点之后才能用
            return self::returnMsg(false,array('code'=>'10001','message'=>'签名在某个时间点之后才能用'));
        }catch(\Firebase\JWT\ExpiredException $e) { // token过期
            return self::returnMsg(false,array('code'=>'10001','message'=>'登陆失败，请重新登陆'));
        }catch(Exception $e) { //其他错误
            return self::returnMsg(false,array('code'=>'10001','message'=>'其他错误'));
        }
    }

    /**
     * 验证后台管理有token
     * @param $token
     * @return array|string
     */
    public static function checkAdmin($token){
        try {
//            JWT::$leeway = 60;//当前时间减去60，把时间留点余地
            $decoded = JWT::decode($token, self::$key, array('HS256')); //HS256方式，这里要和签发的时候对应
            $arr = (array)$decoded;
            $arr = (array)$arr['data'];
            $res = \Tools::getCache($arr['id'].'admin_login_token');
            if(isset($res) && empty($res) === FALSE) {
                if($res == $token){
                    session('user',session('user'));
                    \Tools::setCookie('admin_login_token',$token);
                    \Tools::setCache($arr['id'] . 'admin_login_token', $token, 7200);
                    return 0;
                }else{
                    return 1;
//                    return self::returnMsg(false,array('code'=>'10001','message'=>'账号在其他设备登陆，请重新登陆'));
                }
            }else{
                return 2;
//                return self::returnMsg(false,array('code'=>'10001','message'=>'登陆失败，请重新登陆'));
            }
            return $arr;

        } catch(\Firebase\JWT\SignatureInvalidException $e) { //签名不正确
            return 2;
//            return self::returnMsg(false,array('code'=>'10001','message'=>'签名不正确'));
        }catch(\Firebase\JWT\BeforeValidException $e) { // 签名在某个时间点之后才能用
            return 2;
//            return self::returnMsg(false,array('code'=>'10001','message'=>'签名在某个时间点之后才能用'));
        }catch(\Firebase\JWT\ExpiredException $e) { // token过期
            return 2;
//            return self::returnMsg(false,array('code'=>'10001','message'=>'登陆失败，请重新登陆'));
        }catch(Exception $e) { //其他错误
            return 2;
//            return self::returnMsg(false,array('code'=>'10001','message'=>'其他错误'));
        }
    }

    /**
     * 返回详细信息
     * @param $status 返回状态
     * @param array $array 返回内容
     * @param string $type 类型 json|jsonp|xml|hprose
     * @return array|string
     */
    public static function returnMsg($status,$array=array(), $type = 'json') {
        if($status){
            $arr = array(
                'status'        => (string)'success',
                'code'          => (int) 1,
                "data"          => $array,
                "info"       => "操作成功"
            );
        } else {
            $arr = array(
                'status'        => (string)'error',
                'code'          => (int)$array['code'],
                "info"       => (string)$array['message']
            );
        }
        switch($type){
            case 'json':
                header("Content-Type: text/json");
                if(self::is_php('5.4.0')){
                    $res = json_encode($arr, JSON_UNESCAPED_UNICODE);
                } else {
                    $res = json_encode($arr);
                    $res = urldecode($res);
                }
                break;
            case 'text':
                header("Content-Type: text/html");
                $res = json_encode($arr);
                break;
            case 'jsonp':
                header("Content-Type: text/jsonp");
                $res = $_GET['callback'].'('.json_encode($arr).')';
                break;
            case 'xml':
                header("Content-Type: text/xml");
                $res = Tools::arrayToXml($arr);
                break;
        }
        exit($res);
    }
    /**
     * 判断当前环境php版本是否大于大于等于指定的一个版本
     * @param string $version default=5.5.0
     * @return boolean
     * @author stevema <steve.ma@qcang.cn>
     */
    public static function is_php($version = '5.5.0') {
        $php_version = explode( '-', phpversion() );
        // =0表示版本为5.5.0  ＝1表示大于5.5.0  =-1表示小于5.5.0
        $is_pass = strnatcasecmp( $php_version[0], $version ) >= 0 ? true : false;
        return $is_pass;
    }


    public static function strlen_utf8($str) {
        $i = 0;
        $count = 0;
        $len = strlen ($str);
        while ($i < $len) {
            $chr = ord ($str[$i]);
            $count++; $i++;
            if($i >= $len) break;
            if($chr & 0x80) {
                $chr <<= 1;
                while ($chr & 0x80) {
                    $i++;  $chr <<= 1;
                }
            }
        }
        return ceil($count/70);
    }


    //拆分英语词根
    //获取header
    public static function get_all_header() {
        // 忽略获取的header数据。这个函数后面会用到。主要是起过滤作用
        $ignore = array('host','accept','content-length','content-type');

        $headers = array();
        foreach($_SERVER as $key=>$value){
            if(substr($key, 0, 5)==='HTTP_'){
                //这里取到的都是'http_'开头的数据。
                //前去开头的前5位
                $key = substr($key, 5);
                //把$key中的'_'下划线都替换为空字符串
                $key = str_replace('_', ' ', $key);
                //再把$key中的空字符串替换成‘-’
                $key = str_replace(' ', '-', $key);
                //把$key中的所有字符转换为小写
                $key = strtolower($key);

                //这里主要是过滤上面写的$ignore数组中的数据
                if(!in_array($key, $ignore)){
                    $headers[$key] = $value;
                }
            }
        }
        //输出获取到的header
        return $headers;

    }
    public static function getDateTimeByTime($time = 'NOW', $type = 'Y-m-d H:i:s') {
        $time == 'NOW' ? $time = time() : $time = (Int) $time;
        if($time == '0') {
            return '';
        }
        return date($type, $time);
    }
    public static function formatMoney($money = 0){
        return number_format(intval($money)/100, 2);
    }
    public static function formatTime($money = 0){
        return number_format(intval($money)/60, 2);
    }

    /**
     * 生成二维码
     */
    public static function qrcode($content,$path=false,$logo=''){
        $url = urldecode($content);
        $QrCode = new QrCode($url);
        $QrCode->setWriterByName('png');
        $pngDataUriData = $QrCode->writeDataUri();
        return $pngDataUriData;
    }
    public static function mytime($diff)
    {
        $str = '';
        $day = floor($diff / 86400);
        $free = $diff % 86400;
        $res = '';
        if($day > 0)
        {
            $res.= $day."天";
        }

            if($free>0)
            {
                $hour = floor($free / 3600);
                $free = $free % 3600;
                if($hour>0)
                {
                    $res.=  $hour."小时";
                }
                if($free>0)
                {
                    $min = floor($free / 60);
                    $free = $free % 60;
                    if($min>0)
                    {
                        $res.= $min."分钟";
                    }
                    if($free>0)
                    {
                        $res.= $free."秒";
                    }
                }
            }
            if(empty($res)){
            $res = '0秒';
            }
            return $res;
        }

    /**
     * 将非UTF-8字符集的编码转为UTF-8
     *
     * @param mixed $mixed 源数据
     *
     * @return mixed utf-8格式数据
     */
    public static function charsetToUTF8($mixed)
    {
        if( !empty($mixed) ) {
            $fileType = mb_detect_encoding($mixed, array('UTF-8', 'GBK', 'LATIN1', 'BIG5'));
            //        var_dump($fileType);
            if ($fileType != 'UTF-8') {
                $mixed = mb_convert_encoding($mixed, 'utf-8', $fileType);
            }
        }
        return $mixed;
    }
    /**
     * 求两个日期之间相差的天数
     * (针对1970年1月1日之后，求之前可以采用泰勒公式)
     * @param string $day1
     * @param string $day2
     * @return number
     */
    public static function diffBetweenTwoDays ($day1, $day2)
    {
        $second1 = strtotime($day1);
        $second2 = strtotime($day2);

        if ($second1 < $second2) {
            $tmp = $second2;
            $second2 = $second1;
            $second1 = $tmp;
        }
        return ceil(($second1 - $second2) / 86399);
    }

    /**
     * 后台密码管理
     * @param $passwd
     * @param $oldpasswd
     * @return bool
     */
    public static function think_ucenter_sign($passwd,$oldpasswd){
        $wp_hasher = new \think\PasswordHash(8, TRUE);
        if(!$passwd) {
            return false;
        }
        return $wp_hasher->CheckPassword($passwd, $oldpasswd);
    }
    public static function createPasswd($password){
        $wp_hasher = new \think\PasswordHash(8, TRUE);
        $pwd = $wp_hasher->HashPassword($password);
        return $pwd;
    }
    /**
     * 支付密码和学生密码
     */
    public static function createstudypasswd($passwd,$salt=''){
        if(empty($salt) || $salt == ''){
            $salt = rand(100000, 999999);
        }
        $password = md5($passwd . $salt);
        return array(
            'passwd'    => $password,
            'salt'      => $salt
        );
    }

    /**
     * 校验授权密码
     * @param $oldpasswd
     * @param $passwd
     * @param $salt
     * @param int $type
     * @return bool
     */
    public static function checkpass($oldpasswd,$passwd,$salt,$type = 1){
        if($type == 2 && empty(session('user.pay_passwd')) === FALSE){
            return session('user.pay_passwd') == md5($passwd.session('user.salt'));
        }
        return $oldpasswd == md5($passwd.$salt);
    }


    /**
     * 穿插合并
     * @param $ary
     * @param $ary2
     * @return array
     */
    public static function aryjoinAry($ary,$ary2,$type='1',$t = 0) {
        $itemAry=[];
        //先拿到两个数组中长度较短的那个数组的长度
        $arv_num = count($ary);
        $arv_num2 = count($ary2);
        if ($arv_num < $arv_num2) {
            foreach ($ary as $k => $v) {
                if($k < floor($arv_num2/$type)) {
                    $itemAry[] = $v;
                    for ($i = 1; $i <= $type; $i++) {
                        if (isset($ary2[$i * $k])) {
                            $itemAry[] = $ary2[$i * $k];
                            unset($ary2[$i * $k]);
                        }
                        if ($type >= 2) {
                            if (isset($ary2[$i * $k + 1])) {
                                $itemAry[] = $ary2[$i * $k + 1];
                                unset($ary2[$i * $k + 1]);
                            }
                        }
                        if ($type >= 3) {
                            if (isset($ary2[$i * $k + 2])) {
                                $itemAry[] = $ary2[$i * $k + 2];
                                unset($ary2[$i * $k + 2]);
                            }
                        }
                        if ($type >= 4) {
                            if (isset($ary2[$i * $k + 3])) {
                                $itemAry[] = $ary2[$i * $k + 3];
                                unset($ary2[$i * $k + 3]);
                            }
                        }
                        if ($type >= 5) {
                            if (isset($ary2[$i * $k + 4])) {
                                $itemAry[] = $ary2[$i * $k + 4];
                                unset($ary2[$i * $k + 4]);
                            }
                        }
                        if ($type >= 6) {
                            if (isset($ary2[$i * $k + 5])) {
                                $itemAry[] = $ary2[$i * $k + 5];
                                unset($ary2[$i * $k + 5]);
                            }
                        }
                    }
                }else{
                    if (empty($ary2) === FALSE){
                        $itemAry = array_merge($itemAry,$ary2);
                    }
                    $itemAry[] = $v;
                }
            }
            if(empty($ary2) === FALSE){
                $itemAry = array_merge($itemAry,$ary2);
            }
        } else {
            if($t == 1){//to_do    和  红格配词
                if(empty($ary2)===FALSE){
                    foreach ($ary2 as $k=>$v){
                        $itemAry[] = $v;
                        for ($i = 1; $i <= $type; $i++) {
                            if (isset($ary[$i * $k])) {
                                $itemAry[] = $ary[$i * $k];
                                unset($ary[$i * $k]);
                            }
                            if ($type >= 2) {
                                if (isset($ary[$i * $k + 1])) {
                                    $itemAry[] = $ary[$i * $k + 1];
                                    unset($ary[$i * $k + 1]);
                                }
                            }
                            if ($type >= 3) {
                                if (isset($ary[$i * $k + 2])) {
                                    $itemAry[] = $ary[$i * $k + 2];
                                    unset($ary[$i * $k + 2]);
                                }
                            }
                            if ($type >= 4) {
                                if (isset($ary[$i * $k + 3])) {
                                    $itemAry[] = $ary[$i * $k + 3];
                                    unset($ary[$i * $k + 3]);
                                }
                            }
                            if ($type >= 5) {
                                if (isset($ary[$i * $k + 4])) {
                                    $itemAry[] = $ary[$i * $k + 4];
                                    unset($ary[$i * $k + 4]);
                                }
                            }
                            if ($type >= 6) {
                                if (isset($ary[$i * $k + 5])) {
                                    $itemAry[] = $ary[$i * $k + 5];
                                    unset($ary[$i * $k + 5]);
                                }
                            }
                        }
                    }
                }
            }else{
                foreach ($ary2 as $k => $v) {
                    if($k < floor($arv_num/$type)) {
                        $itemAry[] = $v;
                        for ($i = 1; $i <= $type; $i++) {
                            if (isset($ary[$i * $k])) {
                                $itemAry[] = $ary[$i * $k];
                                unset($ary[$i * $k]);
                            }
                            if ($type >= 2) {
                                if (isset($ary[$i * $k + 1])) {
                                    $itemAry[] = $ary[$i * $k + 1];
                                    unset($ary[$i * $k + 1]);
                                }
                            }
                            if ($type >= 3) {
                                if (isset($ary[$i * $k + 2])) {
                                    $itemAry[] = $ary[$i * $k + 2];
                                    unset($ary[$i * $k + 2]);
                                }
                            }
                            if ($type >= 4) {
                                if (isset($ary[$i * $k + 3])) {
                                    $itemAry[] = $ary[$i * $k + 3];
                                    unset($ary[$i * $k + 3]);
                                }
                            }
                            if ($type >= 5) {
                                if (isset($ary[$i * $k + 4])) {
                                    $itemAry[] = $ary[$i * $k + 4];
                                    unset($ary[$i * $k + 4]);
                                }
                            }
                            if ($type >= 6) {
                                if (isset($ary[$i * $k + 5])) {
                                    $itemAry[] = $ary[$i * $k + 5];
                                    unset($ary[$i * $k + 5]);
                                }
                            }
                        }
                    }else{
                        if (empty($ary) === FALSE){
                            $itemAry = array_merge($itemAry,$ary);
                        }
                        $itemAry[] = $v;
                    }
                    unset($ary2[$k]);
                }
            }
            if(empty($ary) === FALSE){
                $itemAry = array_merge($itemAry,$ary);
            }
        }
        return $itemAry;
    }

    /**
     * 过滤空格
     * @param $str
     * @return mixed
     */
    public static function myTrim($str)
    {
        $search = array(" ","　","\n","\r","\t");
        $replace = array("","","","","");
        return str_replace($search, $replace, $str);
    }
    /**
     * 获取access_token
     */
    public static function getaccess_token($appid,$appsecret){
        $res = \Tools::curl('https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='.$appid.'&secret='.$appsecret,'GET',array());
        return $res;
    }
    /**
     * 发送小程序模板消息
     */
    public static function sendtemp($openid,$access_token,$template_id,$page='',$data){
        $res = \Tools::curl('https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token='.$access_token,'POST',json_encode(array(
            'touser'        =>$openid,
            'template_id'   =>$template_id,
            'page'          => $page,
            'form_id'       =>false,
            'data'          => $data
        )));
        var_dump($res);
    }

    /**
     * 校验是否是微信
     * @return bool
     */
    public static function isWeixin()
    {
//        return true;
        $user_agent = $_SERVER['HTTP_USER_AGENT'];
        if (strpos($user_agent, 'MicroMessenger') === false) {
            return false;
        } else {
            return true;
        }
    }
    /**

     * 数字转换为中文
     * @param  string|integer|float  $num  目标数字
     * @param  integer $mode 模式[true:金额（默认）,false:普通数字表示]
     * @param  boolean $sim 使用小写（默认）
     * @return string
     * $num = '0123648867.789';
    echo $num,'<br>';
    //普通数字的汉字表示
    echo '普通:',number2chinese($num,false),'';
    echo '<br>';
    //金额汉字表示
    echo '金额(简体):',number2chinese($num,true),'';
    echo '<br>';
    echo '金额(繁体):',number2chinese($num,true,false);
     */
    public static function number2chinese($num,$mode = true,$sim = true){
        if(!is_numeric($num)) return '含有非数字非小数点字符！';
        $char    = $sim ? array('零','一','二','三','四','五','六','七','八','九')
            : array('零','壹','贰','叁','肆','伍','陆','柒','捌','玖');
        $unit    = $sim ? array('','十','百','千','','万','亿','兆')
            : array('','拾','佰','仟','','萬','億','兆');
        $retval  = $mode ? '元':'';
        //小数部分
        if(strpos($num, '.')){
            list($num,$dec) = explode('.', $num);
            $dec = strval(round($dec,2));
            if($mode){
                $retval .= "{$char[$dec['0']]}角{$char[$dec['1']]}分";
            }else{
                for($i = 0,$c = strlen($dec);$i < $c;$i++) {
                    $retval .= $char[$dec[$i]];
                }
            }
        }
        //整数部分
        $str = $mode ? strrev(intval($num)) : strrev($num);
        for($i = 0,$c = strlen($str);$i < $c;$i++) {
            $out[$i] = $char[$str[$i]];
            if($mode){
                $out[$i] .= $str[$i] != '0'? $unit[$i%4] : '';
                if($i>1 and $str[$i]+$str[$i-1] == 0){
                    $out[$i] = '';
                }
                if($i%4 == 0){
                    $out[$i] .= $unit[4+floor($i/4)];
                }
            }
        }
        $retval = join('',array_reverse($out)) . $retval;
        return $retval;

    }



    /**
     * SHA加密
     * @param $str
     * @return mixed
     */
    public static function SHA256($str){
        return hash("sha256", $str);
    }

    /**
     * 二维数组乱序
     * @param $list
     * @return array
     */
    public static function shuffle_assoc($list) {
          if (!is_array($list)) return $list;
          $keys = array_keys($list);
          shuffle($keys);
          $random = array();
          foreach ($keys as $key)
            $random[$key] = $list[$key];
          return $random;
        }



    /**
     * 图片转base64
     * $img = 'uploads/01.png';
        $base64_img = base64EncodeImage($img);
        echo '<img src="' . $base64_img . '" />';
     * @param $image_file
     * @return string
     */
    public static function base64EncodeImage ($image_file) {
        $base64_image = '';
        $image_info = getimagesize($image_file);
        $image_data = fread(fopen($image_file, 'r'), filesize($image_file));
        $base64_image = 'data:' . $image_info['mime'] . ';base64,' . chunk_split(base64_encode($image_data));
        return $base64_image;
    }
    /**
     * base64转图片
     * echo base64_image_content($base64_img,"uploads/");
     * @param $base64_image_content
     * @param $path
     * @return bool|string
     */
    public static function base64_image_content($base64_image_content,$path,$filename){
        //匹配出图片的格式
        if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $base64_image_content, $result)){
            $type = $result[2];
            $new_file = $path."/".date('Ymd',time())."/";
            if(!file_exists($new_file)){
                //检查是否有该文件夹，如果没有就创建，并给予最高权限
                mkdir($new_file, 0755,true);
            }
            $new_file = $new_file.$filename.".{$type}";
            if (file_put_contents($new_file, base64_decode(str_replace($result[1], '', $base64_image_content)))){
                return $new_file;
            }else{
                return false;
            }
        }else{
            return false;
        }
    }
    /*
     * 经典的概率算法，
     * $proArr是一个预先设置的数组，
     * 假设数组为：array(100,200,300，400)，
     * 开始是从1,1000 这个概率范围内筛选第一个数是否在他的出现概率范围之内，
     * 如果不在，则将概率空间，也就是k的值减去刚刚的那个数字的概率空间，
     * 在本例当中就是减去100，也就是说第二个数是在1，900这个范围内筛选的。
     * 这样 筛选到最终，总会有一个数满足要求。
     * 就相当于去一个箱子里摸东西，
     * 第一个不是，第二个不是，第三个还不是，那最后一个一定是。
     * 这个算法简单，而且效率非常高，
     * 这个算法在大数据量的项目中效率非常棒。
     */
    public static function get_rand($proArr) {
        $result = '';
        //概率数组的总概率精度
        $proSum = array_sum($proArr);
        //概率数组循环
        foreach ($proArr as $key => $proCur) {
            $randNum = mt_rand(1, $proSum);
            if ($randNum <= $proCur) {
                $result = $key;
                break;
            } else {
                $proSum -= $proCur;
            }
        }
        unset ($proArr);
        return $result;
    }

    /**
     * 过滤掉emoji表情
     * @param $str
     * @return string|string[]|null
     */
    public static function filter_Emoji($value){
        $value = preg_replace_callback('/[\xf0-\xf7].{3}/', function($r) { return '@E' . base64_encode($r[0]);},$value);

        $countt=substr_count($value,"@");
        for ($i=0; $i < $countt; $i++) {
            $c = stripos($value,"@");
            $value=substr($value,0,$c).substr($value,$c+10,strlen($value)-1);
        }
        $value = preg_replace_callback('/@E(.{6}==)/', function($r) {return base64_decode($r[1]);}, $value);
        return $value;
     }
    /**
     * 替换掉数组中的emoji表情
     * @param $arrayString
     * @param string $replaceTo
     * @return mixed|string
     */
    public static function filterEmojiDeep($arrayString,$replaceTo = '?')
    {
        if(is_string($arrayString))
        {
            return self::filterEmoji($arrayString,$replaceTo);
        }
        else if(is_array($arrayString))
        {
            foreach($arrayString as &$array)
            {
                if(is_array($array) || is_string($array))
                {
                    $array = self::filterEmojiDeep($array,$replaceTo);
                }
                else
                {
                    $array = $array;
                }
            }
        }
        return $arrayString;
    }

    /**
     * 替换掉emoji表情
     * @param $text
     * @param string $replaceTo
     * @return mixed|string
     */
    public static function filterEmoji($text, $replaceTo = '?')
    {
        $clean_text = "";
        // Match Emoticons
        $regexEmoticons = '/[\x{1F600}-\x{1F64F}]/u';
        $clean_text = preg_replace($regexEmoticons, $replaceTo, $text);
        // Match Miscellaneous Symbols and Pictographs
        $regexSymbols = '/[\x{1F300}-\x{1F5FF}]/u';
        $clean_text = preg_replace($regexSymbols, $replaceTo, $clean_text);
        // Match Transport And Map Symbols
        $regexTransport = '/[\x{1F680}-\x{1F6FF}]/u';
        $clean_text = preg_replace($regexTransport, $replaceTo, $clean_text);
        // Match Miscellaneous Symbols
        $regexMisc = '/[\x{2600}-\x{26FF}]/u';
        $clean_text = preg_replace($regexMisc, $replaceTo, $clean_text);
        // Match Dingbats
        $regexDingbats = '/[\x{2700}-\x{27BF}]/u';
        $clean_text = preg_replace($regexDingbats, $replaceTo, $clean_text);
        return $clean_text;
    }


    /**
     * 替换手机号或者银行卡号中间为**号
     * @param $mobile
     * @param $sort, 从第几位开始替换
     * @return mixed
     */
    static function handlemobile($mobile,$sort=3){
        $mobile = substr($mobile,0,$sort)."****".substr($mobile,-1,4);
        return $mobile;
    }

    /**
     * 过滤特殊符号
     * @param $strParam
     * @return string|string[]|null
     */
    static function replaceSpecialChar($strParam){
        $regex = "/\/|\~|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\+|\{|\}|\:|\<|\>|\?|\[|\]|\,|\.|\/|\;|\'|\`|\-|\=|\\\|\|/";
        return preg_replace($regex,"",$strParam);
    }

    /*
     * 腾讯使用的是火星坐标系与高德一致
     * GCJ-02(火星，高德)坐标转换成BD-09(百度)坐标
     * @param lon 百度经度
     * @param lat 百度纬度
     */
    function toBD($lon,$lat){
        $x_pi = 3.14159265358979324 * 3000.0 / 180.0;
        $x = $lon;
        $y = $lat;
        $z = sqrt($x * $x + $y * $y) - 0.00002 * sin($y * $x_pi);
        $theta = atan2($y, $x) - 0.000003 * cos($x * $x_pi);
        $lon = $z * cos($theta) + 0.0065;
        $lat = $z * sin($theta) + 0.006;
        // 保留小数点后六位
        $data['lon'] = round($lon, 6);
        $data['lat'] = round($lat, 6);
        return $data;
    }
    /*
     *BD-09(百度)坐标转换成GCJ-02(火星，高德)坐标
     *@param lon 百度经度
     *@param lat 百度纬度
     */
    function toCCJ($lon,$lat){
        $x_pi = 3.14159265358979324 * 3000.0 / 180.0;
        $x = $lon - 0.0065;
        $y = $lat - 0.006;
        $z = sqrt($x * $x + $y * $y) - 0.00002 * sin($y * $x_pi);
        $theta = atan2($y, $x) - 0.000003 * cos($x * $x_pi);
        // $data['gg_lon'] = $z * cos($theta);
        // $data['gg_lat'] = $z * sin($theta);
        $lon = $z * cos($theta);
        $lat = $z * sin($theta);
        // 保留小数点后六位
        $data['gg_lon'] = round($lon, 6);
        $data['gg_lat'] = round($lat, 6);
        return $data;
    }

    /**
     * 生成订单号
     * uid  用户id
     * type  1  图书或者文具   2 plu会员 3 录播  4 研学  4 其他
     * @return void
     */
    public static function createOrder($uid='',$type = 1){
        $orderModel = new \app\api\model\ShopOrder();
        $order_no = $uid .$type. date('Ymd') . mb_substr(time(), 5, 4);
        $orderInfo = $orderModel->where(array(
            'order_no'  => $order_no
        ))->find();
        if(empty($orderInfo)){
            return $order_no;
        }else{
            return self::createOrder($uid,$type);
        }
    }
    /**
     * PHP下载远程图片到本地
     * @param $url string 远程文件地址
     * @author blog.snsgou.com
     */
    static function downfile($url='', $path = '/data/mdimages', $fileType = ['jpg', 'gif', 'png'],$type = 1){
        try {
            if ($url == '')
            {
                return false;
            }
            // 获取文件原文件名
            $suffix = 'png';
            $defaultFileName = time().rand(1000,9999).'.png';
            // 设置保存后的文件名
            $fileName = $defaultFileName == '' ? time() . rand(0, 9) . '.' . $suffix : $defaultFileName;
            // 获取远程文件资源
            if ($type){
                $ch = curl_init();
                $timeout = 15; // 超时时间
                curl_setopt($ch, CURLOPT_URL, $url);
                curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
                curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
                curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
                curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
                $file = curl_exec($ch);
                curl_close($ch);
            }else{
                ob_start();
                readfile($url);
                $file = ob_get_contents();
                ob_end_clean();
            }
            // 设置文件保存路径
            $dirName = $path . '/';
            if (!file_exists($dirName))
            {
                mkdir($dirName, 0777, true);
            }
            // 保存文件
            $res = fopen($dirName . $fileName, 'a');
            fwrite($res, $file);
            fclose($res);
            return $dirName.$fileName;
        } catch (\Exception $e) {
            exit($e->getMessage());
        }
    }
//将文件下载到根目录下的img文件夹中的tmp目录下面
	public static function download($url){
	    $state = @file_get_contents($url,0,null,0,1);//获取网络资源的字符内容
	    if($state){
//	    	$ext = pathinfo($url,PATHINFO_EXTENSION);
            $ext = 'png';
            $dir = '/data/mdimages/'.\Tools::getDateTimeByTime(time(),'Y-m').'/';
	        $filename = $dir.date("dMYHis").'.'.$ext;//文件名称生成
            if(!file_exists($dir)){
                mkdir($dir, 0777, true);
            }
	        ob_start();//打开输出
	        readfile($url);//输出图片文件
	        $img = ob_get_contents();//得到浏览器输出
	        ob_end_clean();//清除输出并关闭
	        $size = strlen($img);//得到图片大小
	        $fp2 = @fopen($filename, "a");
	        fwrite($fp2, $img);//向当前目录写入图片文件，并重新命名
	        fclose($fp2);
	        return $filename;
	    }else{
	        return false;
	    }
	}
    /**
     * unicode解码
     * @param $str
     * @return mixed|string|null
     */
    public static function unicode2utf8($str){
        if(!$str) return $str;
        $decode = json_decode($str);
        if($decode) return $decode;
        $str = '["' . $str . '"]';
        $decode = json_decode($str);
        if(($decode) != 1){
            return $decode[0];
        }
        return $str;
    }
}
